package windbell.domain.risk.impl;

import edu.fudan.langlab.domain.document.IDocument;
import edu.fudan.langlab.domain.statemachine.ModelObjectLogService;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IObjectFactory;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;
import org.springframework.beans.factory.BeanFactory;
import windbell.domain.risk.RiskCheck;
import windbell.domain.risk.RiskCheckItem;
import windbell.domain.risk.RiskCheckItemQrCode;
import windbell.domain.risk.RiskCheckItemStatus;
import windbell.domain.risk.RiskCheckTemplateItem;
import windbell.domain.risk.RiskReport;
import windbell.domain.risk.events.RiskReportEventsManager;
import windbell.domain.risk.impl.RiskCheckImpl;
import windbell.domain.risk.impl.RiskCheckItemQrCodeImpl;
import windbell.domain.risk.impl.RiskCheckTemplateItemImpl;
import windbell.domain.risk.impl.RiskReportImpl;
import windbell.domain.risk.proxy.RiskCheckItemProxy;

@Entity
@DiscriminatorValue("RISKCHECKITEM_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "riskcheckitem")
public class RiskCheckItemImpl extends BaseModelObject implements RiskCheckItem {
  public RiskCheckItemImpl() {
    super();
  }
  
  public RiskCheckItemImpl(final RiskCheck riskCheck) {
    super();
    this.riskCheck = riskCheck;
  }
  
  private RiskCheckItemStatus Status;
  
  public RiskCheckItemStatus getStatus() {
    return this.Status;
  }
  
  private ModelObjectLogService getModelObjectLogService() {
    return getBeanFactory().getBean(ModelObjectLogService.class);
  }
  
  private void _start() {
    
    Status=RiskCheckItemStatus.created;
  }
  
  public void start() {
    if(Status==null){
    	_start();
    	getModelObjectLogService().createLog(this,"Status","Start");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).fireStarted(this);					
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("allready started");
    }
  }
  
  private void _publish() {
    
    Status=RiskCheckItemStatus.checking;
  }
  
  public void publish() {
    if(Status==RiskCheckItemStatus.created){
    	_publish();
    	getModelObjectLogService().createLog(this,"Status","publish");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).firePublish(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _startAudit() {
    
  }
  
  public void startAudit() {
    if(Status==RiskCheckItemStatus.checking){
    	_startAudit();
    	getModelObjectLogService().createLog(this,"Status","startAudit");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).fireStartAudit(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private RiskReport _createReport(final Procedure1<? super RiskReport> init) {
    RiskReport _xblockexpression = null;
    {
      RiskReport _createAndAddtoReports = this.createAndAddtoReports();
      final Procedure1<RiskReport> _function = new Procedure1<RiskReport>() {
          public void apply(final RiskReport it) {
            init.apply(it);
            BeanFactory _beanFactory = RiskCheckItemImpl.this.getBeanFactory();
            RiskReportEventsManager _bean = _beanFactory.<RiskReportEventsManager>getBean(RiskReportEventsManager.class);
            _bean.fireCreated(it);
          }
        };
      final RiskReport report = ObjectExtensions.<RiskReport>operator_doubleArrow(_createAndAddtoReports, _function);
      Status=RiskCheckItemStatus.riskProcessing;
      _xblockexpression = (report);
    }
    return _xblockexpression;
  }
  
  public RiskReport createReport(final Procedure1<? super RiskReport> init) {
    if(Status==RiskCheckItemStatus.checking){
    	RiskReport result = _createReport(init);
    	getModelObjectLogService().createLog(this,"Status","createReport");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).fireCreateReport(this,init);
    	return result;
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("Status.name()");
    }
  }
  
  private IDocument _createDocument(final Procedure1<? super IDocument> init) {
    RiskCheckItemQrCode _createAndAddtoDocuments = this.createAndAddtoDocuments();
    final Procedure1<RiskCheckItemQrCode> _function = new Procedure1<RiskCheckItemQrCode>() {
        public void apply(final RiskCheckItemQrCode it) {
          init.apply(it);
        }
      };
    RiskCheckItemQrCode _doubleArrow = ObjectExtensions.<RiskCheckItemQrCode>operator_doubleArrow(_createAndAddtoDocuments, _function);
    return _doubleArrow;
  }
  
  public IDocument createDocument(final Procedure1<? super IDocument> init) {
    if(Status==RiskCheckItemStatus.checking||Status==RiskCheckItemStatus.riskProcessing){
    	IDocument result = _createDocument(init);
    	getModelObjectLogService().createLog(this,"Status","createDocument");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).fireCreateDocument(this,init);
    	return result;
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("Status.name()");
    }
  }
  
  private void _removeDocument(final IDocument document) {
    this.removeFromDocuments(((RiskCheckItemQrCode) document));
  }
  
  public void removeDocument(final IDocument document) {
    if(Status==RiskCheckItemStatus.checking||Status==RiskCheckItemStatus.riskProcessing){
    	_removeDocument(document);
    	getModelObjectLogService().createLog(this,"Status","removeDocument");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).fireRemoveDocument(this,document);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _deleteReport(final RiskReport report) {
    
    this.removeFromReports(report);
    BeanFactory _beanFactory = this.getBeanFactory();
    RiskReportEventsManager _bean = _beanFactory.<RiskReportEventsManager>getBean(RiskReportEventsManager.class);
    _bean.fireDeleted(report);
  }
  
  public void deleteReport(final RiskReport report) {
    if(Status==RiskCheckItemStatus.checking||Status==RiskCheckItemStatus.riskProcessing){
    	_deleteReport(report);
    	getModelObjectLogService().createLog(this,"Status","deleteReport");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).fireDeleteReport(this,report);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _finish(final String comment) {
    
    this.comment = comment;
    Status=RiskCheckItemStatus.finished;
    this.riskCheck.$itemFinished();
  }
  
  public void finish(final String comment) {
    if(Status==RiskCheckItemStatus.checking||Status==RiskCheckItemStatus.riskProcessing){
    	_finish(comment);
    	getModelObjectLogService().createLog(this,"Status","finish");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskCheckItemEventsManager.class).fireFinish(this,comment);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  public Boolean isCreated() {
    return windbell.domain.risk.RiskCheckItemStatus.created==Status;
  }
  
  public Boolean isChecking() {
    return windbell.domain.risk.RiskCheckItemStatus.checking==Status;
  }
  
  public Boolean isRiskProcessing() {
    return windbell.domain.risk.RiskCheckItemStatus.riskProcessing==Status;
  }
  
  public Boolean isFinished() {
    return windbell.domain.risk.RiskCheckItemStatus.finished==Status;
  }
  
  @JoinColumn(name = "riskCheck_id")
  @ManyToOne(targetEntity = RiskCheckImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskCheck riskCheck;
  
  public RiskCheck getRiskCheck() {
    return this.riskCheck;
  }
  
  @OneToMany(targetEntity = RiskReportImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "riskCheckItem")
  private Collection<RiskReport> reports = new java.util.ArrayList<windbell.domain.risk.RiskReport>();;
  
  public Collection<RiskReport> getReports() {
    return this.reports;
  }
  
  public RiskReport createAndAddtoReports() {
    getReports().size();
    windbell.domain.risk.RiskReport riskReport = new windbell.domain.risk.impl.RiskReportImpl(this);
    getObjectFactory().create(riskReport);
    getReports().add(riskReport);
    riskReport.start();
    return riskReport;
    
  }
  
  public RiskReport createAndAddtoReports(final Procedure1<RiskReport> updater) {
    getReports().size();
    windbell.domain.risk.RiskReport riskReport = new windbell.domain.risk.impl.RiskReportImpl(this);
    getObjectFactory().create(riskReport);
    getReports().add(riskReport);
    updater.apply(riskReport);
    riskReport.start();
    return riskReport;
    
  }
  
  public RiskCheckItem removeAllReports() {
    for(RiskReport obj : this.reports){
    	getObjectFactory().delete(obj);
    }
    this.reports.clear();
    return this;	
    
  }
  
  public RiskCheckItem removeFromReports(final RiskReport riskReport) {
    this.reports.remove(riskReport);
    getObjectFactory().delete(riskReport);
    return this;
    
  }
  
  @OneToMany(targetEntity = RiskCheckItemQrCodeImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "riskCheckItem")
  private Collection<RiskCheckItemQrCode> documents = new java.util.ArrayList<windbell.domain.risk.RiskCheckItemQrCode>();;
  
  public Collection<RiskCheckItemQrCode> getDocuments() {
    return this.documents;
  }
  
  public RiskCheckItemQrCode createAndAddtoDocuments() {
    getDocuments().size();
    windbell.domain.risk.RiskCheckItemQrCode riskCheckItemQrCode = new windbell.domain.risk.impl.RiskCheckItemQrCodeImpl(this);
    getObjectFactory().create(riskCheckItemQrCode);
    getDocuments().add(riskCheckItemQrCode);
    return riskCheckItemQrCode;
    
  }
  
  public RiskCheckItemQrCode createAndAddtoDocuments(final Procedure1<RiskCheckItemQrCode> updater) {
    getDocuments().size();
    windbell.domain.risk.RiskCheckItemQrCode riskCheckItemQrCode = new windbell.domain.risk.impl.RiskCheckItemQrCodeImpl(this);
    getObjectFactory().create(riskCheckItemQrCode);
    getDocuments().add(riskCheckItemQrCode);
    return riskCheckItemQrCode;
    
  }
  
  public RiskCheckItem removeAllDocuments() {
    for(RiskCheckItemQrCode obj : this.documents){
    	getObjectFactory().delete(obj);
    }
    this.documents.clear();
    return this;	
    
  }
  
  public RiskCheckItem removeFromDocuments(final RiskCheckItemQrCode riskCheckItemQrCode) {
    this.documents.remove(riskCheckItemQrCode);
    getObjectFactory().delete(riskCheckItemQrCode);
    return this;
    
  }
  
  @JoinColumn(name = "checkItem_id")
  @ManyToOne(targetEntity = RiskCheckTemplateItemImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskCheckTemplateItem checkItem;
  
  public RiskCheckTemplateItem getCheckItem() {
    return this.checkItem;
  }
  
  public RiskCheckItem setCheckItem(final RiskCheckTemplateItem checkItem) {
    this.checkItem = checkItem;
    return this;			
    
  }
  
  private String comment;
  
  public String getComment() {
    return this.comment;
  }
  
  public RiskCheckItem setComment(final String comment) {
    this.comment = comment;
    return this;			
    
  }
  
  public static RiskCheckItem create(final RiskCheck riskCheck, final IObjectFactory objectFactory) {
    windbell.domain.risk.RiskCheckItem riskCheckItem = new windbell.domain.risk.impl.RiskCheckItemImpl(
    	riskCheck
    );
    objectFactory.create(riskCheckItem);
    riskCheckItem.start();
    return riskCheckItem;			
    
  }
  
  public static RiskCheckItem createRiskCheckItemImpl(final RiskCheck riskCheck, final IObjectFactory objectFactory, final Procedure1<RiskCheckItem> init) {
    windbell.domain.risk.RiskCheckItem riskCheckItem = new windbell.domain.risk.impl.RiskCheckItemImpl(
    	riskCheck
    );
    objectFactory.create(riskCheckItem);
    init.apply(riskCheckItem);
    riskCheckItem.start();
    return riskCheckItem;			
    
  }
  
  public RiskCheckItemProxy toProxy() {
    windbell.domain.risk.proxy.RiskCheckItemProxy proxy = new windbell.domain.risk.proxy.RiskCheckItemProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    proxy.setStatus(this.getStatus().name());
    return proxy;
    
  }
}
